//
// Created by macos on 2021/11/20.
//

#include <stdbool.h>
#include <yaml.h>
#include "yml.h"
#include "logger.h"

void load_yml_config(map_t *yml_config, const char *yml_filename) {
    *yml_config = map_new();
    unsigned char tokens[8][MAX_KEY_LENGTH];
    FILE *fh = fopen(yml_filename, "r");
    yaml_parser_t parser;
    yaml_token_t token;   /* new variable */

    /* Initialize parser */
    if (!yaml_parser_initialize(&parser))
        fputs("Failed to initialize parser!\n", stderr);
    if (fh == NULL)
        fputs("Failed to open file!\n", stderr);

    /* Set input file */
    yaml_parser_set_input_file(&parser, fh);
    /* BEGIN new code */
    unsigned char i = 0;
    bool key = true;
    do {
        yaml_parser_scan(&parser, &token);
        switch (token.type) {
            /* Stream start/end */
            case YAML_STREAM_START_TOKEN:
                i = 0;
                break;
            case YAML_STREAM_END_TOKEN:
                break;
                /* Token types (read before actual token) */
            case YAML_KEY_TOKEN:
                key = true;
                break;
            case YAML_VALUE_TOKEN:
                key = false;
                break;
                /* Block delimeters */
            case YAML_BLOCK_SEQUENCE_START_TOKEN:
                break;
            case YAML_BLOCK_ENTRY_TOKEN:
                break;
            case YAML_BLOCK_END_TOKEN:
                i--;
                break;
                /* Data */
            case YAML_BLOCK_MAPPING_START_TOKEN:
                i++;
                break;
            case YAML_SCALAR_TOKEN:
                if (key)
                    strcpy(tokens[i], token.data.scalar.value);
                else {
                    unsigned char yml_key[MAX_KEY_LENGTH];
                    memset(yml_key, 0, MAX_KEY_LENGTH);
                    unsigned char j;
                    for (j = 1; j <= i; j++) {
                        strcat(yml_key, tokens[j]);
                        if (j != i)
                            strcat(yml_key, ".");
                    }
                    char *value = strndup((char *) token.data.scalar.value, token.data.scalar.length);
                    map_put(*yml_config, (char *) yml_key, value, token.data.scalar.length);
                    printf("%s=%s\n", yml_key, value);
                }
                /* Others */
            default:
                break;
//                printf("Got token of type %d\n", token.type);
        }
        if (token.type != YAML_STREAM_END_TOKEN)
            yaml_token_delete(&token);
    } while (token.type != YAML_STREAM_END_TOKEN);
    yaml_token_delete(&token);
    /* END new code */

    /* Cleanup */
    yaml_parser_delete(&parser);
    fclose(fh);
}

unsigned char *get_yml_string(map_t yml_config, char *key) {
    void *value = map_get(yml_config, key);
    return (unsigned char *) value;
}


int64_t get_yml_int64(map_t yml_config, char *key) {
    void *value = map_get(yml_config, key);
    char *v = (char *) value;
    char *p_end;
    return strtoll(v, &p_end, 10);
}

void close_yml(map_t yml_config) {
    map_free(yml_config);
}